﻿using System;
using System.Threading.Tasks;
using Hopscotch.Common.Contracts.AppService;
using Hopscotch.Common.Logging;
using Hopscotch.Domain.Common;
using Hopscotch.Presentation.Common.Threading;


namespace Hopscotch.Presentation.Common.Commands
{
    public class SaveEntityCommand<T, TKey> : CommandBase, ICommandBase
        where T : DomainBase<TKey>
        where TKey : struct
    {
        private readonly ILogger logger;
        private readonly IDispatcher dispatcher;
        private readonly IToolViewModel<T, TKey> toolViewModel;
        private readonly IDomainService<T, TKey> domainService;

        public SaveEntityCommand(
            IDispatcher dispatcher,
            IToolViewModel<T, TKey> toolViewModel,
            IDomainService<T, TKey> domainService)
        {
            this.dispatcher = dispatcher;
            this.toolViewModel = toolViewModel;
            this.domainService = domainService;

            this.logger = AppLogger.CreateLogger("SaveEntityCommand");
        }

        public bool CanExecute(object parameter)
        {
            return !toolViewModel.IsBusy;
        }

        public async void Execute(object parameter)
        {
            toolViewModel.IsSavePressed = true;

            toolViewModel.Validate();
            if (!toolViewModel.HasErrors)
            {
                toolViewModel.IsBusy = true;
                var entity = toolViewModel.Model;

                try
                {
                    entity = await Task.Factory.StartNew<T>(() => domainService.Save(toolViewModel.Model));
                    toolViewModel.SetModel(entity);

                    toolViewModel.IsBusy = false;
                    toolViewModel.ToolEditMode = ToolEditMode.None;
                }
                catch (Exception ex)
                {
                    var id = entity != null ? entity.Id : default(TKey);
                    string msg = string.Format("Error saving entity of Type={0}, Id={1}", typeof(T).Name, id);
                    logger.Error(msg, ex);

                    //Turn off BusyIndicator and raise error notification
                    toolViewModel.IsBusy = false;
                    toolViewModel.RaiseErrorNotification(msg, ex);
                }
            }
        }
    }
}
